#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
存储相关数据模型
"""

from sqlalchemy import Column, Integer, String, BigInteger, Boolean, DateTime, Text, Index
from sqlalchemy.orm import relationship, Session
from datetime import datetime
from typing import List, Optional
from .base import Base, BaseRepository, QueryCondition


class VirtualStorage(Base):
    """虚拟存储表 - 存储文件的实际数据和元信息"""
    __tablename__ = 'virtual_storage'
    
    id = Column(Integer, primary_key=True, autoincrement=True, comment='主键ID')
    file_id = Column(String(64), nullable=False, unique=True, comment='文件MD5哈希值，作为文件唯一标识')
    original_filename = Column(String(255), nullable=False, comment='原始文件名（上传时名称）')
    file_size_bytes = Column(BigInteger, nullable=False, comment='文件大小（字节）')
    media_type = Column(Integer, nullable=False, comment='媒体类型')
    large_icon_url = Column(String(500), comment='大缩略图URL')
    small_icon_url = Column(String(500), comment='小缩略图URL')
    file_extension = Column(String(20), comment='文件扩展名（小写，不含点）')
    reference_count = Column(Integer, default=0, comment='引用计数')
    download_count = Column(Integer, default=0, comment='下载总次数')
    status = Column(Integer, nullable=False, default=1, comment='状态')
    is_hot = Column(Boolean, default=False, comment='是否热门文件')
    cloud_provider = Column(String(50), nullable=False, comment='云存储提供商')
    cloud_file_id = Column(String(255), nullable=True, comment='云盘文件ID')
    cloud_download_url = Column(String(1000), comment='云盘下载链接（临时）')
    url_expires_at = Column(DateTime, comment='下载链接过期时间')
    local_data = Column(Text(16777215), comment='本地存储的文件数据（Base64编码）')  # 使用MEDIUMTEXT支持更大文件
    created_at = Column(DateTime, nullable=False, default=datetime.utcnow, comment='创建时间')
    last_modified_at = Column(DateTime, nullable=False, default=datetime.utcnow, onupdate=datetime.utcnow, comment='最后修改时间')
    last_accessed_at = Column(DateTime, comment='最后访问时间')
    
    # 关联关系
    virtual_files = relationship("VirtualFile", back_populates="storage")
    
    # 索引
    __table_args__ = (
        Index('idx_file_id', 'file_id'),
        Index('idx_file_size', 'file_size_bytes'),
        Index('idx_media_type', 'media_type'),
        Index('idx_cloud_provider', 'cloud_provider'),
    )
    
    @property
    def mime_type(self):
        """根据文件扩展名获取MIME类型"""
        if not self.file_extension:
            return 'application/octet-stream'
        
        # 常见MIME类型映射
        mime_map = {
            'txt': 'text/plain',
            'html': 'text/html',
            'css': 'text/css',
            'js': 'application/javascript',
            'json': 'application/json',
            'xml': 'application/xml',
            'pdf': 'application/pdf',
            'doc': 'application/msword',
            'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'xls': 'application/vnd.ms-excel',
            'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'ppt': 'application/vnd.ms-powerpoint',
            'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            'zip': 'application/zip',
            'rar': 'application/x-rar-compressed',
            '7z': 'application/x-7z-compressed',
            'tar': 'application/x-tar',
            'gz': 'application/gzip',
            'jpg': 'image/jpeg',
            'jpeg': 'image/jpeg',
            'png': 'image/png',
            'gif': 'image/gif',
            'bmp': 'image/bmp',
            'webp': 'image/webp',
            'svg': 'image/svg+xml',
            'ico': 'image/x-icon',
            'mp4': 'video/mp4',
            'avi': 'video/x-msvideo',
            'mkv': 'video/x-matroska',
            'mov': 'video/quicktime',
            'wmv': 'video/x-ms-wmv',
            'flv': 'video/x-flv',
            'mp3': 'audio/mpeg',
            'wav': 'audio/wav',
            'flac': 'audio/flac',
            'aac': 'audio/aac',
            'ogg': 'audio/ogg',
        }
        return mime_map.get(self.file_extension.lower(), 'application/octet-stream')


class VirtualStorageRepository(BaseRepository):
    """虚拟存储Repository"""
    
    def __init__(self):
        super().__init__(VirtualStorage)
    
    def find_by_file_id(self, file_id: str) -> Optional[VirtualStorage]:
        """根据文件ID查找存储"""
        condition = QueryCondition()
        condition.eq(VirtualStorage.file_id, file_id)
        return self.get_one(condition)
    
    def find_by_cloud_provider(self, cloud_provider: str) -> List[VirtualStorage]:
        """根据云存储提供商查找文件"""
        condition = QueryCondition()
        condition.eq(VirtualStorage.cloud_provider, cloud_provider)
        return self.list_by_condition(condition, order_by='created_at', desc_order=True)
    
    def find_by_media_type(self, media_type: int) -> List[VirtualStorage]:
        """根据媒体类型查找文件"""
        condition = QueryCondition()
        condition.eq(VirtualStorage.media_type, media_type)
        return self.list_by_condition(condition, order_by='file_size_bytes', desc_order=True)
    
    def find_by_file_extension(self, file_extension: str) -> List[VirtualStorage]:
        """根据文件扩展名查找文件"""
        condition = QueryCondition()
        condition.eq(VirtualStorage.file_extension, file_extension.lower())
        return self.list_by_condition(condition, order_by='created_at', desc_order=True)
    
    def find_by_size_range(self, min_size: int = None, max_size: int = None) -> List[VirtualStorage]:
        """根据文件大小范围查找文件"""
        condition = QueryCondition()
        if min_size is not None:
            condition.ge(VirtualStorage.file_size_bytes, min_size)
        if max_size is not None:
            condition.le(VirtualStorage.file_size_bytes, max_size)
        return self.list_by_condition(condition, order_by='file_size_bytes', desc_order=True)
    
    def find_hot_files(self) -> List[VirtualStorage]:
        """查找热门文件"""
        condition = QueryCondition()
        condition.eq(VirtualStorage.is_hot, True)
        return self.list_by_condition(condition, order_by='download_count', desc_order=True)
    
    def find_by_status(self, status: int) -> List[VirtualStorage]:
        """根据状态查找文件"""
        condition = QueryCondition()
        condition.eq(VirtualStorage.status, status)
        return self.list_by_condition(condition, order_by='created_at', desc_order=True)
    
    def find_expired_urls(self) -> List[VirtualStorage]:
        """查找下载链接已过期的文件"""
        condition = QueryCondition()
        condition.lt(VirtualStorage.url_expires_at, datetime.utcnow())
        condition.is_not_null(VirtualStorage.url_expires_at)
        return self.list_by_condition(condition)
    
    def create_storage(self, file_id: str, original_filename: str, file_size_bytes: int,
                      media_type: int, cloud_provider: str, file_extension: str = None,
                      cloud_file_id: str = None, local_data: str = None) -> VirtualStorage:
        """创建存储记录"""
        storage = VirtualStorage(
            file_id=file_id,
            original_filename=original_filename,
            file_size_bytes=file_size_bytes,
            media_type=media_type,
            cloud_provider=cloud_provider,
            file_extension=file_extension,
            cloud_file_id=cloud_file_id,
            local_data=local_data
        )
        return self.save(storage)
    
    def update_download_url(self, storage_id: int, download_url: str, expires_at: datetime) -> bool:
        """更新下载链接"""
        return self.update_by_id(storage_id, 
                               cloud_download_url=download_url,
                               url_expires_at=expires_at)
    
    def increment_download_count(self, storage_id: int) -> bool:
        """增加下载次数"""
        storage = self.get_by_id(storage_id)
        if storage:
            new_count = storage.download_count + 1
            return self.update_by_id(storage_id, 
                                   download_count=new_count,
                                   last_accessed_at=datetime.utcnow())
        return False
    
    def increment_reference_count(self, storage_id: int) -> bool:
        """增加引用计数"""
        storage = self.get_by_id(storage_id)
        if storage:
            new_count = storage.reference_count + 1
            return self.update_by_id(storage_id, reference_count=new_count)
        return False
    
    def decrement_reference_count(self, storage_id: int) -> bool:
        """减少引用计数"""
        storage = self.get_by_id(storage_id)
        if storage and storage.reference_count > 0:
            new_count = storage.reference_count - 1
            return self.update_by_id(storage_id, reference_count=new_count)
        return False
    
    def mark_as_hot(self, storage_id: int) -> bool:
        """标记为热门文件"""
        return self.update_by_id(storage_id, is_hot=True)
    
    def unmark_as_hot(self, storage_id: int) -> bool:
        """取消热门文件标记"""
        return self.update_by_id(storage_id, is_hot=False)
    
    def update_status(self, storage_id: int, status: int) -> bool:
        """更新状态"""
        return self.update_by_id(storage_id, status=status)
    
    def cleanup_unreferenced_files(self) -> int:
        """清理无引用的文件"""
        condition = QueryCondition()
        condition.eq(VirtualStorage.reference_count, 0)
        return self.delete_by_condition(condition)